//-----------------------------------------------------------
//  Grenades.cs - Class to add grenades to torque via script
//-----------------------------------------------------------
// This script file is an easy way to add grenades to your
// FPS.  Just exec this script from game.cs and bind a key 
// to call the throwGrenadeDB function
//-----------------------------------------------------------

datablock AudioProfile(HandGrenadePullpinSound)
{
	filename = "~/data/shapes/grenade/pullpin.wav";
	description = AudioDefault3d;
	preload = true;
};

datablock AudioProfile(HandGrenadeThrowSound)
{
	filename = "~/data/shapes/grenade/throw.wav";
	description = AudioDefault3d;
	preload = true;
};

datablock AudioProfile(HandGrenadeExplosionSound)
{
	filename = "~/data/shapes/grenade/explode.wav";
	description = AudioDefault3d;
	preload = true;
};

datablock ParticleData(HandGrenadeExplosionFire)
{
   textureName          = "~/data/shapes/particles/fire";
   dragCoeffiecient     = 100.0;
   gravityCoefficient   = 0;
   inheritedVelFactor   = 0.25;
   constantAcceleration = 0.1;
   lifetimeMS           = 500;
   lifetimeVarianceMS   = 400;
   useInvAlpha =  false;
   spinRandomMin = -80.0;
   spinRandomMax =  80.0;

   colors[0]     = "0.8 0.4 0 0.8";
   colors[1]     = "0.2 0.0 0 0.8";
   colors[2]     = "0.0 0.0 0.0 0.0";

   sizes[0]      = 1.5;
   sizes[1]      = 3;
   sizes[2]      = 5;

   times[0]      = 0.0;
   times[1]      = 0.5;
   times[2]      = 1.0;
};

datablock ParticleEmitterData(HandGrenadeExplosionFireEmitter)
{
   ejectionPeriodMS = 150;
   periodVarianceMS = 100;
   ejectionVelocity = 0.8;
   velocityVariance = 0.5;
   thetaMin         = 0.0;
   thetaMax         = 180.0;
   lifetimeMS       = 250;
   particles		= "HandGrenadeExplosionFire";
};

datablock ParticleData(HandGrenadeExplosionSmoke)
{
   textureName          = "~/data/shapes/particles/smoke";
   dragCoeffiecient     = 100.0;
   gravityCoefficient   = 0;
   inheritedVelFactor   = 0.25;
   constantAcceleration = -0.30;
   lifetimeMS           = 610;
   lifetimeVarianceMS   = 200;
   useInvAlpha =  true;
   spinRandomMin = -80.0;
   spinRandomMax =  80.0;

   colors[0]     = "0.56 0.36 0.26 1.0";
   colors[1]     = "0.2 0.2 0.2 1.0";
   colors[2]     = "0.0 0.0 0.0 0.0";

   sizes[0]      = 4.0;
   sizes[1]      = 5.0;
   sizes[2]      = 6.0;

   times[0]      = 0.0;
   times[1]      = 0.5;
   times[2]      = 1.0;
};

datablock ParticleEmitterData(HandGrenadeExplosionSmokeEmitter)
{
   ejectionPeriodMS = 300;
   periodVarianceMS = 0;
   ejectionVelocity = 4;
   velocityVariance = 2;
   thetaMin         = 0.0;
   thetaMax         = 180.0;
   lifetimeMS       = 50;
   particles		= "HandGrenadeExplosionSmoke";
};

datablock ParticleData(HandGrenadeExplosionSparks)
{
   textureName          = "~/data/shapes/particles/spark";
   dragCoefficient      = 1;
   gravityCoefficient   = 0.0;
   inheritedVelFactor   = 0.2;
   constantAcceleration = 0.0;
   lifetimeMS           = 500;
   lifetimeVarianceMS   = 350;

   colors[0]     = "0.60 0.40 0.30 1.0";
   colors[1]     = "0.60 0.40 0.30 1.0";
   colors[2]     = "1.0 0.40 0.30 0.0";

   sizes[0]      = 0.25;
   sizes[1]      = 0.15;
   sizes[2]      = 0.15;

   times[0]      = 0.0;
   times[1]      = 0.5;
   times[2]      = 1.0;
};

datablock ParticleEmitterData(HandGrenadeExplosionSparkEmitter)
{
   ejectionPeriodMS = 3;
   periodVarianceMS = 0;
   ejectionVelocity = 5;
   velocityVariance = 1;
   ejectionOffset   = 0.0;
   thetaMin         = 0;
   thetaMax         = 180;
   phiReferenceVel  = 0;
   phiVariance      = 360;
   overrideAdvances = false;
   orientParticles  = true;
   lifetimeMS       = 100;
   particles		= "HandGrenadeExplosionSparks";
};

datablock ParticleData(HandGrenadeDebrisTrail)
{
   textureName          = "~/data/shapes/particles/fire";
   dragCoefficient      = 1;
   gravityCoefficient   = 0;
   inheritedVelFactor   = 0;
   windCoefficient      = 0;
   constantAcceleration = 0;
   lifetimeMS           = 800;
   lifetimeVarianceMS   = 100;
   spinSpeed     = 0;
   spinRandomMin = -90.0;
   spinRandomMax =  90.0;
   useInvAlpha   = true;

   colors[0]     = "0.8 0.3 0.0 1.0";
   colors[1]     = "0.1 0.1 0.1 0.7";
   colors[2]     = "0.1 0.1 0.1 0.0";

   sizes[0]      = 0.2;
   sizes[1]      = 0.3;
   sizes[2]      = 0.4;

   times[0]      = 0.1;
   times[1]      = 0.2;
   times[2]      = 1.0;
};


datablock ParticleEmitterData(HandGrenadeDebrisTrailEmitter)
{
   ejectionPeriodMS = 30;
   periodVarianceMS = 0;
   ejectionVelocity = 0.0;
   velocityVariance = 0.0;
   ejectionOffset   = 0.0;
   thetaMin         = 170;
   thetaMax         = 180;
   phiReferenceVel  = 0;
   phiVariance      = 360;
   //overrideAdvances = false;
   //orientParticles  = true;
   lifetimeMS       = 5000;
   particles = "HandGrenadeDebrisTrail";
};



datablock ParticleData(HandGrenadeDebrisSpark)
{
   textureName          = "~/data/shapes/particles/fire";
   dragCoefficient      = 0;
   gravityCoefficient   = 0.0;
   windCoefficient      = 0;
   inheritedVelFactor   = 0.5;
   constantAcceleration = 0.0;
   lifetimeMS           = 500;
   lifetimeVarianceMS   = 50;
   spinRandomMin = -90.0;
   spinRandomMax =  90.0;
   useInvAlpha   = false;

   colors[0]     = "0.8 0.2 0 1.0";
   colors[1]     = "0.8 0.2 0 1.0";
   colors[2]     = "0 0 0 0.0";

   sizes[0]      = 0.2;
   sizes[1]      = 0.3;
   sizes[2]      = 0.1;

   times[0]      = 0.0;
   times[1]      = 0.5;
   times[2]      = 1.0;
};

datablock ParticleEmitterData(HandGrenadeDebrisSparkEmitter)
{
   ejectionPeriodMS = 20;
   periodVarianceMS = 0;
   ejectionVelocity = 0.5;
   velocityVariance = 0.25;
   ejectionOffset   = 0.0;
   thetaMin         = 0;
   thetaMax         = 90;
   phiReferenceVel  = 0;
   phiVariance      = 360;
   overrideAdvances = false;
   orientParticles  = false;
   lifetimeMS       = 300;
   particles = "HandGrenadeDebrisSpark";
};

datablock ExplosionData(HandGrenadeDebrisExplosion)
{
   emitter[0] = HandGrenadeDebrisSparkEmitter;

   // Turned off..
   shakeCamera = false;
   impulseRadius = 0;
   lightStartRadius = 0;
   lightEndRadius = 0;
};

// Debris object
datablock DebrisData(HandGrenadeExplosionDebris)
{
   shapeFile = "~/data/shapes/crossbow/debris.dts";
   emitters = "HandGrenadeDebrisTrailEmitter";
   explosion = HandGrenadeDebrisExplosion;
   
   elasticity = 0.6;
   friction = 0.5;
   numBounces = 1;
   bounceVariance = 1;
   explodeOnMaxBounce = true;
   staticOnMaxBounce = false;
   snapOnMaxBounce = false;
   minSpinSpeed = 0;
   maxSpinSpeed = 700;
   render2D = false;
   lifetime = 2;
   lifetimeVariance = 0.4;
   velocity = 5;
   velocityVariance = 0.5;
   fade = false;
   useRadiusMass = true;
   baseRadius = 0.3;
   gravModifier = 0.5;
   terminalVelocity = 6;
   ignoreWater = true;
};







datablock ExplosionData(HandGrenadeExplosion)
{
   soundProfile = HandGrenadeExplosionSound;
   lifeTimeMS = 800;

   // Volume particles
   particleEmitter = HandGrenadeExplosionFireEmitter;
   particleDensity = 55;
   particleRadius = 2;

   // Point emission
   emitter[0] = HandGrenadeExplosionSmokeEmitter;
   emitter[1] = HandGrenadeExplosionSparkEmitter;
   
   // Camera Shaking
   shakeCamera = true;
   camShakeFreq = "10.0 11.0 10.0";
   camShakeAmp = "1.0 1.0 1.0";
   camShakeDuration = 0.5;
   camShakeRadius = 10.0;

   // Exploding debris
   debris = HandGrenadeExplosionDebris;
   debrisThetaMin = 0;
   debrisThetaMax = 60;
   debrisPhiMin = 0;
   debrisPhiMax = 360;
   debrisNum = 4;
   debrisNumVariance = 3;
   debrisVelocity = 0.8;
   debrisVelocityVariance = 0.5;
   
   // Impulse
   impulseRadius = 5;
   impulseForce = 25;

   // Dynamic light
   lightStartRadius = 6;
   lightEndRadius = 3;
   lightStartColor = "0.5 0.5 0";
   lightEndColor = "0 0 0";
};


datablock ItemData(HandGrenadeAmmo)
{
   // Mission editor category
   category = "Ammo";

   // Add the Ammo namespace as a parent.  The ammo namespace provides
   // common ammo related functions and hooks into the inventory system.
   className = "Ammo";

   // Basic Item properties
   shapeFile = "~/data/shapes/grenade/ammo.dts";
   mass = 1;
   elasticity = 0.2;
   friction = 0.6;

   // Dynamic properties defined by the scripts
   pickUpName = "hand grenades";
   maxInventory = 3;
};



//datablock ItemData(Grenade)
datablock ProjectileData(HandGrenade)
{   
	category = "HandGrenade";
	projectileShapeName = "~/data/shapes/grenade/grenade.dts";
	explodeDelay = 2500; 
	explosion = HandGrenadeExplosion;
	
	directDamage        = 0;
	radiusDamage        = 20;
	damageRadius        = 5;
	areaImpulse         = 25;
	
	gravityMod			= 1.0;
	muzzleVelocity		= 30;
	armingDelay         = 90000;
	lifetime            = 90000;
	fadeDelay           = 90000;
	isBallistic			= true;
	bounceElasticity    = 0.2;
	bounceFriction      = 0.08;
};


function HandGrenade::Explode(%this, %obj)
{
	echo("HandGrenade::Explode called");
	%obj.ExplodeEventID=0;
	%pos = %obj.getPosition();
	%explosion = new (Explosion)()
	{
		dataBlock = %this.explosion;
		position = %pos;
	};
	MissionCleanup.add(%explosion);

	radiusDamage(%obj, %pos, %this.damageRadius, %this.radiusDamage, "radius", %this.areaImpulse);
	%obj.delete();
}


// If you do not want the grenade to explode if someone walks over/into it, just remove this
// this oncollision member call....
//function Grenade::onCollision(%this,%obj,%col)
//function Grenade::onCollision( %this, %obj, %col, %fade, %pos, %normal )
//{   
//	echo("Grenade::onCollision -> " @ %col.getDataBlock().className);

//	if ( (%col.getDataBlock().className $= "armor") && (%obj.ExplodeEventID) )
//	{
//		%this.Explode(%obj);
//	}
//}

function ShapeBase::throwGrenadeDB(%this, %GrenadeTypeDB, %client)
{       
	//%obj.decInventory(%this.ammo,0);
	// Play the pull pin sound
	serverPlay3D(HandGrenadePullpinSound,%client.player.getTransform());
	// Play throw sound
	schedule(300, 0, serverPlay3D, HandGrenadeThrowSound, %client.player.getTransform());
	// Play an animation that looks like we're throwing 
	%client.player.schedule(300, setActionThread, "lookms");
	// Create the grenade
	%this.schedule(500, "doGrenadeThrow", %GrenadeTypeDB, %client);
}


function ShapeBase::doGrenadeThrow(%this, %GrenadeTypeDB, %client)
{
	echo("ShapeBase::doGrenadeThrow"); 
	
	// Spawn the grenade directly in front of the player
	%playerPos = getBoxCenter(%client.player.getWorldBox());
	%forward = %client.player.getEyeVector();
	%initialPos = vectorAdd(%playerPos, %forward);
	
	// Generate the vector to throw the grenade
	%eye = %this.getEyeVector();  
	%vec = vectorScale(%eye, %GrenadeTypeDB.muzzleVelocity);
	//%muzzleVelocity = VectorScale(%muzzleVelocity, %GrenadeTypeDB.muzzleVelocity);
	%dot = vectorDot("0 0 1",%eye);  
	if (%dot < 0)       
		%dot = -%dot;
	// Put a small up-arc on the grenade
	%muzzleVelocity = vectorAdd(%vec,vectorScale("0 0 7",1 - %dot)); 
	//%muzzleVelocity = vectorAdd(%vec,%this.getVelocity()); //this will cause the players inertia to affect the throw
	
	// Create the projectile
	%item = new Projectile()	
	{     
		dataBlock		= %GrenadeTypeDB;
		initialVelocity	= %muzzleVelocity;
		initialPosition	= %initialPos;
		sourceObject	= %client.player;
		sourceSlot		= 3;
		client			= %client;
	}; 
	MissionCleanup.add(%item);

	//set detonantion delay   
	%item.ExplodeEventID = %GrenadeTypeDB.schedule(%GrenadeTypeDB.explodeDelay, "Explode", %item);
}

// Tell a client to throw a grenade
function serverCmdthrowGrenadeNow(%client)
{
	// Only throw the grenade if it's been 1 seconds from the last throw
	if (%client.player.lastThrownGrenadeTime + 1 <= $Sim::Time)
	{
		%client.player.lastThrownGrenadeTime = $Sim::Time;
		%client.player.throwGrenadeDB(HandGrenade, %client);
	}
	else
	{
		return;
	}
}

// Throw grenade's by using the 'g' key 
// TODO: Maybe move this to the right-mouse button?
moveMap.bindCmd(keyboard, "g", "commandToServer(\'throwGrenadeNow\');", "");
